#ifndef HOST_H
#define HOST_H

#include <Windows.h>
#include "commdef.h"

/*
 *	PubKey
 */
class PubKey
{
public:
	PubKey( void );
	~PubKey();

	void Set( BYTE* key, int len, int e, int capa );
	void UnSet( void );
	const BYTE* GetKey(){ return m_key; }
	int GetKeyLen(){ return m_keyLen; }
	int GetExponent(){ return m_e; }
	bool KeyBlob( BYTE* blob, int maxLen, int* len );
	int GetKeyBlobLen(){ return m_keyLen + 8 + 12; }
	void SetByBlob( BYTE* blob, int capa );
	int GetCapa(){ return m_capa; }

protected:
	BYTE*	m_key;
	int		m_keyLen;
	int		m_e;
	int		m_capa;
};

/*
 *	HostSub
 */
struct THostSub
{
	char	userName[MAX_NAMEBUF];
	char	hostName[MAX_NAMEBUF];
	ULONG	addr;
	int		portNum;
};

/*
 *	Host
 */
struct THost
{
	THostSub	hostSub;
	char	nickName[MAX_NAMEBUF];
	char	groupName[MAX_NAMEBUF];
	ULONG	hostStatus;
	time_t	updateTime;
	int		priority;
	int		refCnt;
	PubKey	pubKey;
	int		cryptSpec;

	THost() : refCnt(0){}
	~THost(){ refCnt = 0; }
	int RefCnt( int cnt = 0 ){ return refCnt += cnt; }
};

/*
 *	THosts
 */
class CHosts
{
public:
	enum Kind{ NAME, ADDR, NAME_ADDR, MAX_ARRAY };
	bool _enable[MAX_ARRAY];

	CHosts( void );
	~CHosts();

	void Enable( Kind kind, bool enable ){ _enable[kind] = enable; }
	bool AddHost( THost* host );
	bool DelHost( THost* host );
	int  GetHostCnt(){ return m_hostCnt; }
	THost* GetHost( int index, Kind kind = NAME ){ return m_hosts[kind][index]; }
	THost* GetHostByName( THostSub* hostSub ){ return _enable[NAME] ? Search( NAME, hostSub ) : NULL; }
	THost* GetHostByAddr( THostSub* hostSub ){ return _enable[ADDR] ? Search( ADDR, hostSub ) : NULL; }
	THost* GetHostByNameAddr( THostSub* hostSub ){ return _enable[NAME_ADDR] ? Search( NAME_ADDR, hostSub) : NULL;}
	int   PriorityHostCnt( int priority, int range = 1 );

protected:
	THost* Search( Kind kind, THostSub* hostSub, int* insertIndex = NULL );
	int	Cmp( THostSub* hostSub1, THostSub* hostSub2, Kind kind );

protected:
	int		m_hostCnt;
	THost**	m_hosts[MAX_ARRAY];
};

/*
 *	SendEntry
 */
enum SendStatus { ST_GETCRYPT, ST_MAKECRYPTMSG, ST_MAKEMSG, ST_SENDMSG, ST_DONE };
class CSendEntry
{
public:
	CSendEntry() : m_msg( NULL ), m_host( NULL ){}
	~CSendEntry(){ delete[] m_msg; if( m_host && m_host->RefCnt(-1) == 0 ) delete m_host; }
	void SetMsg( char* msg, int len ){ delete[] m_msg; m_msg = new char[m_msgLen=len]; memcpy( m_msg, msg, len ); }
	const char* GetMsg(){ return m_msg; }
	int GetMsgLen(){ return m_msgLen; }
	void SetHost( THost* host ){ (m_host = host)->RefCnt(1); }
	THost* GetHost(){ return m_host; }
	void SetStatus( SendStatus status ){ m_status = status; }
	SendStatus GetStatus(){ return m_status; }
	void SetCommand( UINT command ){ m_command = command; }
	UINT GetCommand(){ return m_command; }
private:
	THost*		m_host;
	SendStatus	m_status;
	UINT		m_command;
	char*		m_msg;
	int			m_msgLen;
};

bool IsSameHost( THostSub *hostSub1, THostSub *hostSub2 );

inline bool IsSameHostEx( THostSub *host, THostSub *host2 ) 
{ 
	return IsSameHost( host, host2 ) && host->addr == host2->addr && host->portNum == host2->portNum ? true : false;
}

#endif	// HOST_H